# -*- coding: utf-8 -*-

"""
Date: 2023/2/24 15:23
Author: Darker
"""
import math
import re
import traceback
from typing import Text, Optional, Dict, Union, List, Tuple, Any, NoReturn

import attr
from requests import exceptions

from log import logger
from utils.request_utils import myRequest
from utils import get_value_from_json, trans_str_to_list


@attr.s(auto_attribs=True)
class Tapd(object):
    """tapd相关操作"""

    @property
    def statusTool(self) -> Text:
        return "id;closed;title;reject_time;reopen_time;severity;priority;status;current_owner;reporter;created;fixer;" \
               "resolved;de;closer;custom_field_four;"

    def check_network_process(self) -> Optional[bool]:
        """检查网络状态"""
        url = "company/participant_projects"
        data = {
            "from": "left_tree2"
        }
        response = myRequest.head(url=url, data=data)
        if response.status_code != 200:
            logger.error(f"网络无法访问，状态码：{response.status_code}")
        else:
            return True

    def get_project_ids(self) -> Optional[Dict]:
        """获取项目id"""
        url = "company/my_take_part_in_projects_list"
        response = myRequest.get(url=url)
        return dict(re.findall(r'object-id=.(.*?)">.*?<a title="(.*?)"', response.text, re.S))

    def get_release_ids(self, releaseId: Text) -> Optional[Dict]:
        """
        根据项目id获取发布计划
        :param releaseId: 项目id
        :return:
        """
        url = f"{releaseId}/releases/lists"
        totalPage = 999
        params = {
            "page": 1,
            "perpage": 20,
            "sort_name": "name",
            "order": "DESC"
        }
        releaseInfoDict = {}
        while params.get("page", 1) <= totalPage:
            try:
                response = myRequest.get(url=url, params=params)
            except (exceptions.ConnectionError, exceptions.RequestException):
                logger.error("连接错误，请检查网络; 确认是否开启代理工具, 如fiddler、VPN")
                logger.error(traceback.format_exc())
                return
            except Exception:
                logger.error("未知异常，请上报管理员")
                logger.error(traceback.format_exc())
                raise
            if "<title>登录-TAPD</title>" in response.text:
                logger.error("tapd-cookie无效，请重新获取")
                logger.error(traceback.format_exc())
                return
            # 获取最大页码数
            totalCountList = re.findall(r'<span class="list-count">共<span class=\'count\'>(\d+)</span>', response.text)
            match totalCountList:
                case []:
                    totalPage = 1
                case _:
                    totalPage = math.ceil(int(totalCountList[0]) / params.get("perpage"))
            releaseInfoDict.update(dict(zip(re.findall(r'<div id="operation_(.*?)" class="', response.text, re.S),
                                            re.findall(r'<td title="(.*?)">', response.text, re.S))))
            params["page"] += 1
        return releaseInfoDict

    def get_iteration_versions(self, workspaceIds: Union[Text, List]):
        """
        根据发布计划获取迭代版本
        :param workspaceIds: 发布计划ids
        :return:
        """
        if isinstance(workspaceIds, Text):
            workspaceIds = [workspaceIds]
        page = 1
        url = "api/new_filter/new_filter/get_options"
        data = {
            "entity_type": "common",
            "workspace_ids": workspaceIds,
            "field": "iteration_id",
            "is_system": 1,
            "use_scene": "search_filter",
            "Filter": {
                "iteration_id": {
                    "use_page": 1,
                    "Filter": {
                        "status": "~done"
                    },
                    "page": page,
                    "perpage": 50
                }
            },
            "dsc_token": "bGdaKSgSBhk69NTJ"
        }
        iterationData = {}
        while True:
            response = myRequest.post(url=url, data=data, **{"headers": {"x-requested-with": "XMLHttpRequest"}})
            if response.json().get("meta").get("code") != "0":
                return
            iterationNameList = get_value_from_json(response.json().get("data"), "label")
            iterationIdList = get_value_from_json(response.json().get("data"), "value")
            iterationData.update(dict(zip(iterationIdList, iterationNameList)))
            if len(iterationIdList) < 50 and len(iterationNameList) < 50:
                data["Filter"]["iteration_id"]["page"] = page = page + 1
            else:
                return iterationData

    def get_bug_fields_user_view_and_list(self, workspaceIds: Text, confId: Text = "", queryToken="") -> \
            Tuple[Optional[Text], Optional[Text]]:
        """
        获取缺陷字段用户视图和缺陷列表viewId, confId
        :param workspaceIds: 项目id
        :param confId: 配置id
        :param queryToken: 状态保持
        :return: tuple(viewId, confId)
        """
        url = "api/aggregation/bug_aggregation/get_bug_fields_userview_and_list"
        data = {
            "workspace_id": workspaceIds,
            "conf_id": confId,
            "sort_name": "",
            "order": "",
            "perpage": 50,
            "page": 1,
            "selected_workspace_ids": "",
            "query_token": queryToken,
            "location": "/bugtrace/bugreports/my_view",
            "target": f"{workspaceIds}/bug/normal",
            "entity_types": ["bug"],
            "user_scene": "bug_list",
            "return_url": f"https://www.tapd.cn/tapd_fe/{workspaceIds}/bug/list?confId={confId}&page=1&"
                          f"queryToken={queryToken}",
            "dsc_token": "bGdaKSgSBhk69NTJ"
        }
        response = myRequest.post(url=url, data=data)
        viewInfo = get_value_from_json(response.json(), "view_info")[0]
        viewId, confId = viewInfo.get("id"), viewInfo.get("conf_id")
        return viewId, confId

    def get_bug_list_by_url(self, data: Union[Text, Dict] = None, page: int = 1, perPage: int = 100,
                            flag: Text = "bug_list", **kwargs) -> Union[List, Tuple, int]:
        """
        获取缺陷字段用户视图和缺陷列表
        :param data: 请求参数
        :param page: 页码数
        :param perPage: 每页展示多少条
        :param flag: 获取的数据类型
        :param kwargs: 扩展字段
        """
        if not data:
            data = {}
        url = "api/entity/bugs/bugs_list"
        if isinstance(data, Dict):
            data = data
        elif isinstance(data, Text):
            data = eval(data)
        workspaceId = data.get("workspace_id")
        data["page"] = page
        data["perpage"] = perPage
        response = myRequest.post(url=url, data=data)
        if response.status_code != 200:
            return
        totalCount = get_value_from_json(response.json(), "total_count")[0]
        match flag:
            case "bugs_list":
                return get_value_from_json(response.json(), "Bug") if totalCount else []
            case "info":
                viewInfo = get_value_from_json(response.json(), "view_info")[0]
                viewId, confId = viewInfo.get("id"), viewInfo.get("conf_id")
                return viewId, confId, workspaceId, int(totalCount)
            case _:
                return int(totalCount)

    def get_bugs_list(self, workspaceId: Text, confId: Text, startTime: Text = None, endTime: Text = None,
                      title: Text = None, iterationId: Text = None, system: Text = None, testPhase: Text = None,
                      releaseId: Text = None, queryToken: Text = None, page: int = 1, perPage: int = 100,
                      flag: Text = "bugs_list") -> Union[List, int, NoReturn]:
        """
        获取缺陷字段用户视图和缺陷列表
        :param workspaceId: 项目id
        :param confId: 配置id
        :param startTime: 开始时间
        :param endTime: 结束时间
        :param title: 标题
        :param iterationId: 迭代id
        :param system: 操作系统
        :param testPhase: 测试阶段
        :param releaseId: 发布计划id
        :param queryToken: 状态保持
        :param page: 页码数
        :param perPage: 每页多少条
        :param flag: 数据类型
        :return:
        """
        releaseId = trans_str_to_list(releaseId)
        testPhase = trans_str_to_list(testPhase)
        system = trans_str_to_list(system)
        iterationId = trans_str_to_list(iterationId)
        created = f"{startTime} 00:00,{endTime} 23:59"
        url = "api/entity/bugs/bugs_list"
        data = {
            "workspace_id": workspaceId,
            "conf_id": confId,
            "sort_name": "",
            "order": "",
            "perpage": perPage,
            "page": page,
            "selected_workspace_ids": [],
            "filter_expr": {
                "data": [
                    {"fieldOption": "like", "fieldType": "input", "fieldSystemName": "name", "fieldDisplayName": "标题",
                     "selectOption": [], "value": title, "fieldIsSystem": "1"},
                    {"fieldOption": "in", "fieldType": "select", "fieldSystemName": "iteration_id",
                     "fieldDisplayName": "迭代", "selectOption": [], "value": iterationId, "fieldIsSystem": "1"},
                    {"fieldOption": "between", "fieldType": "datetime", "fieldSystemName": "created",
                     "fieldDisplayName": "创建时间", "selectOption": [], "value": created, "fieldIsSystem": "1"},
                    {"fieldOption": "in", "fieldType": "select", "fieldSystemName": "os",
                     "fieldDisplayName": "操作系统", "selectOption": [], "value": system, "fieldIsSystem": "1"},
                    {"fieldOption": "in", "fieldType": "select", "fieldSystemName": "testphase",
                     "fieldDisplayName": "测试阶段", "selectOption": [], "value": testPhase, "fieldIsSystem": "1"},
                    {"fieldOption": "in", "fieldType": "select", "fieldSystemName": "release_id",
                     "fieldDisplayName": "发布计划", "selectOption": [], "value": releaseId, "fieldIsSystem": "1"},
                ],
                "optionType": "AND",
                "needInit": True
            },
            "return_url": f"https://www.tapd.cn/tapd_fe/{workspaceId}/bug/list?page={page}&queryToken={queryToken}",
            "dsc_token": "bGdaKSgSBhk69NTJ"
        }
        response = myRequest.post(url=url, data=data)
        if response.status_code != 200:
            return
        totalCount = get_value_from_json(response.json(), "total_count")[0]
        match flag:
            case "bugs_list":
                return get_value_from_json(response.json(), "Bug") if totalCount else []
            case _:
                return int(totalCount)

    def get_show_fields(self, workspaceId: Text, viewId: Text) -> Optional[Text]:
        """
        获取缺陷展示字段拼接的str
        :param workspaceId: 项目id
        :param viewId: 视图id
        :return:
        """
        url = "api/basic/userviews/get_show_fields"
        params = {
            "id": viewId,
            "workspace_id": workspaceId,
            "location": "/bugtrace/bugreports/my_views",
            "form": "show_fields"
        }
        response = myRequest.get(url=url, params=params)
        if response .status_code != 200:
            return
        fieldList = get_value_from_json(response.json(), "fields")[0]
        return ";".join(fieldList)

    def set_show_fields(self, workspaceId: Text, viewId: Text, customFields: Text) -> Optional[bool]:
        """
        设置缺陷显示字段
        :param workspaceId: 项目id
        :param viewId: 视图id
        :param customFields: 视图显示字段
        :return:
        """
        url = "api/basic/userviews/edit_show_fields"
        data = {
            "workspace_id": workspaceId,
            "id": viewId,
            "location": "/bugtrace/bugreports/my_view",
            "custom_fields": customFields,
            "dsc_token": "bGdaKSgSBhk69NTJ"
        }
        response = myRequest.post(url=url, data=data)
        if response.status_code != 200:
            return
        return True


tapd = Tapd()
if __name__ == '__main__':
    r = tapd.get_iteration_versions(['1167410840001001775'])
    print(r)
